package com.supor.aiot.home.ui.home;

import android.annotation.SuppressLint;
import android.app.Application;
import android.text.TextUtils;

import com.alibaba.fastjson.JSONObject;
import com.android.baseconfig.base.BaseSharedPreferences;
import com.android.baseconfig.base.RxBus3;
import com.android.baseconfig.common.config.HttpConstant;
import com.android.baseconfig.common.utils.GsonUtil;
import com.android.baseconfig.common.utils.Logc;
import com.android.baseconfig.common.utils.StringUtils;
import com.android.baseconfig.common.utils.ThreadUtils;
import com.supor.aiot.common.app.AppAgent;
import com.supor.aiot.common.app.AppInit;
import com.supor.aiot.common.app.Constants;
import com.supor.aiot.common.app.SuporPresenter;
import com.supor.aiot.common.app.api.CommonImpl;
import com.supor.aiot.common.app.api.DeviceImpl;
import com.supor.aiot.common.base.BaseViewModel;
import com.supor.aiot.common.entity.BannerInfo;
import com.supor.aiot.common.entity.ChiefMachineData;
import com.supor.aiot.common.entity.DeviceInfo;
import com.supor.aiot.common.entity.OvenData;
import com.supor.aiot.common.entity.Result;
import com.supor.aiot.common.entity.RiceCookerData;
import com.supor.aiot.common.entity.WaterPurifierData;
import com.supor.aiot.common.helper.GlobalDataCache;
import com.supor.aiot.common.helper.WsHelper;
import com.supor.aiot.common.push.PushMsgService;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

import androidx.annotation.NonNull;
import androidx.lifecycle.MutableLiveData;
import io.reactivex.rxjava3.functions.Consumer;

public class HomeViewModel extends BaseViewModel {
    private int index = 0;
    /**
     * 绑定列表
     */
    private MutableLiveData<Result> deviceListData = new MutableLiveData<>();
    /**
     * 更新单个绑定设备item
     */
    private MutableLiveData<Integer> notifyData = new MutableLiveData<>();
    private MutableLiveData<Result> unbindData = new MutableLiveData<>();
    private MutableLiveData<Result> locationData = new MutableLiveData<>();
    private MutableLiveData<Result> bannerData = new MutableLiveData<>();

    // 存放电饭煲当前菜谱ID，{key=mac, value=recipeID}
    private ConcurrentHashMap<String, Integer> recipeIDMaps = new ConcurrentHashMap<>();

    // 存放电饭煲当前菜谱名称，{key=mac, value=recipeName}
    private ConcurrentHashMap<String, String> recipeNameMaps = new ConcurrentHashMap<>();

    public HomeViewModel(@NonNull Application application) {
        super(application);
        RxBus3.getInstance().register(Constants.Tag.LOCATION_PERMISSION, (Consumer<String>) s -> {
            Logc.i("LOCATION_PERMISSION: rxbus");
            AppInit.getInstance().doRequestLocation();
        }, getClass());
        RxBus3.getInstance().register(Constants.Tag.LOCATION, (Consumer<String>) s -> {
            if (GlobalDataCache.locationInfo != null) {
                locationData.setValue(new Result.Success(GlobalDataCache.locationInfo));
            }
        }, getClass());
        RxBus3.getInstance().register(Constants.Tag.BINDING_STATUS, (Consumer<String>) s -> {
            if (GlobalDataCache.deviceTree != null) {
                deviceListData.setValue(new Result.Success(GlobalDataCache.deviceTree.device));
            } else {
                deviceListData.setValue(new Result.Success(new ArrayList<DeviceInfo>()));
            }

            // 延时1秒后主动发送指令拉取状态
            ThreadUtils.execute(() -> {
                // 针对电饭煲，刷新需重新拉取设备状态
                if (GlobalDataCache.deviceTree != null && GlobalDataCache.deviceTree.device != null) {
                    for (DeviceInfo info : GlobalDataCache.deviceTree.device) {
                        if (Constants.Type.TYPE_RICE_COOKER_85A.equalsIgnoreCase(info.model)) {
                            SuporPresenter.getInstance().sendCmd(2, info.mac, info.did, "[\"appointmentTime\"]");
                        } else if (Constants.Type.TYPE_WATER_PURIFIER.equalsIgnoreCase(info.type)) {
                            SuporPresenter.getInstance().sendCmd(2, info.mac, info.did, "[\"power\"]");
                        }
                    }
                }
            }, 1000);
        }, getClass());
        RxBus3.getInstance().register(Constants.Tag.ONLINE_STATUS, (Consumer<String>) did -> {
            if (did == null) {
                return;
            }
            List<DeviceInfo> device = GlobalDataCache.deviceTree.device;
            for (int i = 0; i < device.size(); i++) {
                DeviceInfo info = device.get(i);
                if (info.did.equalsIgnoreCase(did)) {
                    notifyData.setValue(i);
                    break;
                }
            }
        }, getClass());
        RxBus3.getInstance().register(Constants.Tag.LOGIN, (Consumer<String>) s -> {
            locationData.setValue(new Result.Success(GlobalDataCache.locationInfo));
        }, this.getClass());
        RxBus3.getInstance().register(Constants.Tag.LOGOUT, (Consumer<String>) s -> {
            deviceListData.setValue(new Result.Success(new ArrayList<DeviceInfo>()));
            locationData.setValue(new Result.Success(GlobalDataCache.locationInfo));
        }, getClass());
        RxBus3.getInstance().register(Constants.Tag.SNOTI, (Consumer<JSONObject>) jsonObject -> {
            // Logc.e("HomeViewModel: " + jsonObject);
            if (jsonObject == null) {
                return;
            }
            try {
                JSONObject cloneObject = (JSONObject) jsonObject.clone();
                String did = cloneObject.getString(Constants.Key.DID);
                JSONObject data = cloneObject.getJSONObject(Constants.Key.ATTRS);
                String originalData = data.toJSONString();
                String pType =
                        StringUtils.ascIIToStr(data.getJSONArray(Constants.Key.PRODUCT_TYPE).toString());
                String pModel =
                        StringUtils.ascIIToStr(data.getJSONArray(Constants.Key.PRODUCT_MODEL).toString());
                data.put(Constants.Key.PRODUCT_TYPE, pType);
                data.put(Constants.Key.PRODUCT_MODEL, pModel);
                try {
                    data.put(Constants.Key.WORK_STATUS, StringUtils.arrayToInt(data.getJSONArray(
                            Constants.Key.WORK_STATUS).toArray()));
                } catch (Exception e) {
                    e.printStackTrace();
                }

                // Logc.i("HomeViewModel: " + data);
                if (Constants.Type.TYPE_CHEF_MACHINE.equalsIgnoreCase(pType)) {
                    data.put(Constants.Key.WORK_TIME, StringUtils.arrayToInt(data.getJSONArray(
                            Constants.Key.WORK_TIME).toArray()));
                    ChiefMachineData machineData = GsonUtil.getInstance().toObject(data.toString(),
                            ChiefMachineData.class);
                    List<DeviceInfo> device = GlobalDataCache.deviceTree.device;
                    for (int i = 0; i < device.size(); i++) {
                        DeviceInfo info = device.get(i);
                        if (info.did.equalsIgnoreCase(did)) {
                            info.deviceData = machineData;
                            info.originalData = originalData;
                            // 上一帧是工作中的状态需要把dropFirstFrame置为false，目的是从设备详情页返回
                            // 到设备列表页面能够直接刷新工作中的数据
                            if (machineData.machineStatus != 0 && machineData.machineStatus != 5) {
                                if (info.lastFrame) {
                                    info.dropFirstFrame = false;
                                } else {
                                    info.lastFrame = true;
                                }

                                // 丢掉第一帧数据
                                if (info.dropFirstFrame) {
                                    info.dropFirstFrame = false;
                                } else {
                                    notifyData.setValue(i);
                                    SuporPresenter.getInstance().reportCmd(info.mac, did, originalData);
                                }
                                return;
                            } else {
                                info.lastFrame = false;
                                info.dropFirstFrame = true;
                            }
                            notifyData.setValue(i);
                            SuporPresenter.getInstance().reportCmd(info.mac, did, originalData);
                            break;
                        }
                    }
                } else if (Constants.Type.TYPE_OVEN.equalsIgnoreCase(pType)) {

                    data.put(Constants.Key.PRODUCT_ID, StringUtils.ascIIToStr(data.getJSONArray(
                            Constants.Key.PRODUCT_ID).toString()));
                    String recipeName = StringUtils.ascIIToStr(data.getJSONArray(
                            "recipeName").toString());
                    if (TextUtils.isEmpty(recipeName)) {
                        data.put("recipeName", "");
                    }
                    OvenData ovenData = GsonUtil.getInstance().toObject(data.toString(),
                            OvenData.class);
                    List<DeviceInfo> device = GlobalDataCache.deviceTree.device;
                    for (int i = 0; i < device.size(); i++) {
                        DeviceInfo info = device.get(i);
                        if (info.did.equalsIgnoreCase(did)) {
                            info.deviceData = ovenData;
                            info.originalData = originalData;
                            notifyData.setValue(i);
                            SuporPresenter.getInstance().reportCmd(info.mac, did, originalData);
                            break;
                        }
                    }
                } else if (Constants.Type.TYPE_RICE_COOKER.equalsIgnoreCase(pType)) {

                    data.put(Constants.Key.PRODUCT_ID, StringUtils.ascIIToStr(data.getJSONArray(
                            Constants.Key.PRODUCT_ID).toString()));
                    data.put(Constants.Key.APPOINTMENT_TIME, StringUtils.arrayToInt(data.getJSONArray(
                            Constants.Key.APPOINTMENT_TIME).toArray()));
                    data.put(Constants.Key.HOLDING_TIME, StringUtils.arrayToInt(data.getJSONArray(
                            Constants.Key.HOLDING_TIME).toArray()));
                    data.put(Constants.Key.RECIPE_ID, StringUtils.arrayToInt(data.getJSONArray(
                            Constants.Key.RECIPE_ID).toArray()));
                    RiceCookerData riceCookerData = GsonUtil.getInstance().toObject(data.toString(),
                            RiceCookerData.class);
                    List<DeviceInfo> device = GlobalDataCache.deviceTree.device;
                    for (int i = 0; i < device.size(); i++) {
                        DeviceInfo info = device.get(i);
                        if (info.did.equalsIgnoreCase(did)) {
                            // 根据recipeID更新recipeName
                            int recipeID = riceCookerData.recipeID;
                            String mac = info.mac;
                            boolean isUpdate = false;
                            if (recipeID > 0) {
                                Integer oldRecipeId = recipeIDMaps.get(mac);
                                if (oldRecipeId == null || oldRecipeId != recipeID) {
                                    // 更新recipeID
                                    recipeIDMaps.put(mac, recipeID);
                                    final int ii = i;
                                    isUpdate = true;
                                    // 调接口更新recipeName
                                    CommonImpl.getInstance().getRecipe(recipeID, mac).subscribe(result -> {
                                        if (result.isSuccess()) {
                                            JSONObject parseObject = JSONObject.parseObject(result.data);
                                            String rName = parseObject.getString(Constants.Key.RECIPE_NAME);
                                            if (rName != null) {
                                                riceCookerData.recipeName = rName;
                                                recipeNameMaps.put(mac, rName);
                                                info.deviceData = riceCookerData;
                                                info.originalData = originalData;
                                                notifyData.setValue(ii);
                                                SuporPresenter.getInstance().reportCmd(info.mac, did, originalData);
                                            }
                                        }
                                    });
                                }
                            }
                            if (!isUpdate) {
                                // 防止下拉刷新或者数据推送时菜谱名称被清空
                                riceCookerData.recipeName = recipeNameMaps.get(info.mac);
                                info.deviceData = riceCookerData;
                                info.originalData = originalData;
                                notifyData.setValue(i);
                                SuporPresenter.getInstance().reportCmd(info.mac, did, originalData);
                            }
                            break;
                        }
                    }
                } else if (Constants.Type.TYPE_WATER_PURIFIER.equalsIgnoreCase(pType)) {
                    data.put(Constants.Key.PRODUCT_ID, StringUtils.ascIIToStr(data.getJSONArray(
                            Constants.Key.PRODUCT_ID).toString()));
                    WaterPurifierData waterPurifierData = GsonUtil.getInstance().toObject(data.toString(),
                            WaterPurifierData.class);
                    List<DeviceInfo> device = GlobalDataCache.deviceTree.device;
                    for (int i = 0; i < device.size(); i++) {
                        DeviceInfo info = device.get(i);
                        if (info.did.equalsIgnoreCase(did)) {
                            info.deviceData = waterPurifierData;
                            info.originalData = originalData;

                            notifyData.setValue(i);
                            SuporPresenter.getInstance().reportCmd(info.mac, did, originalData);
                            break;
                        }
                    }
                } else {
                    List<DeviceInfo> device = GlobalDataCache.deviceTree.device;
                    for (int i = 0; i < device.size(); i++) {
                        DeviceInfo info = device.get(i);
                        if (info.did.equalsIgnoreCase(did)) {
                            SuporPresenter.getInstance().reportCmd(info.mac, did, originalData);
                            break;
                        }
                    }
                }

            } catch (Exception e) {
                Logc.e("HomeViewModel: " + e);
                e.printStackTrace();
            }
        }, getClass());

        RxBus3.getInstance().register("EXIT_LOGIN", (Consumer<String>) s -> {
            PushMsgService.unbindUser();
            BaseSharedPreferences.setString(AppAgent.getApp(), Constants.Key.USER_INFO, "");
            BaseSharedPreferences.setString(AppAgent.getApp(), HttpConstant.TOKEN, "");
            GlobalDataCache.userInfo = null;
            GlobalDataCache.deviceTree = null;
            AppAgent.setLogin(false);
            WsHelper.getInstance().exit();
            RxBus3.getInstance().post(Constants.Tag.LOGOUT, Constants.Value.SUCCESS);
        }, getClass());
    }

    public void refresh() {
        switchTab(index);
    }

    public MutableLiveData<Result> getDeviceListData() {
        return deviceListData;
    }

    public MutableLiveData<Integer> getNotifyData() {
        return notifyData;
    }

    public MutableLiveData<Result> getUnbindData() {
        return unbindData;
    }

    public MutableLiveData<Result> getLocationData() {
        return locationData;
    }

    public MutableLiveData<Result> getBannerData() {
        return bannerData;
    }

    @SuppressLint("CheckResult")
    public void getBannerList() {
        CommonImpl.getInstance().getBanner(10, Constants.Value.APP_BANNER, Constants.Value.BANNER_NORMAL).subscribe(result -> {
            List<BannerInfo> bannerInfoList = result.data.rows;
            bannerData.setValue(new Result.Success(bannerInfoList));
        }, throwable -> {
            Logc.e("accept: " + throwable);
            bannerData.setValue(new Result.Error(new Exception(throwable)));
        });
    }

    public void getBindDeviceList() {
        if (GlobalDataCache.deviceTree != null) {
            List<DeviceInfo> devices = GlobalDataCache.deviceTree.device;
            GlobalDataCache.getBindDevice();
            deviceListData.setValue(new Result.Success(devices));
        } else {
            GlobalDataCache.getBindDevice();
            deviceListData.setValue(new Result.Success(new ArrayList<DeviceInfo>()));
        }
    }

    @SuppressLint("CheckResult")
    public void unbindDevice(String mac, String did, int position) {
        DeviceImpl.getInstance().unbind(mac, did).subscribe(result -> {
            unbindData.setValue(new Result.Success(position));
        }, throwable -> {
            Logc.e("accept: " + throwable);
            unbindData.setValue(new Result.Error(new Exception(throwable)));
        });
    }

    public void switchTab(int id) {
        index = id;
    }

    public void finish() {
        RxBus3.getInstance().unregister(getClass());
    }

}
